package com.bupt.ilink.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bupt.ilink.entity.pojo.store.StoreFlowInfo;
import com.bupt.ilink.entity.pojo.store.*;
import com.bupt.ilink.entity.store.*;
import com.bupt.ilink.mapper.*;
import com.bupt.ilink.service.StoreService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service
@Transactional
public class StoreServiceImpl implements StoreService {

    @Autowired
    private StoreFlowMapper storeFlowMapper;

    @Autowired
    private StoreFlowTagMapper storeFlowTagMapper;

    @Autowired
    private TagMapper tagMapper;

    @Autowired
    private LikeMapper likeMapper;

    @Autowired
    private DownloadMapper downloadMapper;

    @Override
    public CheckStoreResult check(){
        return new CheckStoreResult(true);
    }

    @Override
    public UploadFlowResult uploadFlow(UploadFlowInfo flowInfo) {
        flowInfo.selfGenerateMetaData();
        storeFlowMapper.insert(flowInfo);
        for (String tagId : flowInfo.getTags()) {
            storeFlowTagMapper.insertStoreFlowTag(flowInfo.getFlowId(), tagId);

        }
        return new UploadFlowResult(flowInfo.getFlowId());
    }

    @Override
    public UpdateFlowResult updateFlow(UploadFlowInfo flowInfo) {
        flowInfo.selfGenerateMetaData();
        storeFlowMapper.updateById(flowInfo);
        HashSet<String> oldTags =new HashSet<>(storeFlowTagMapper.getTagIdsByFlowId(flowInfo.getFlowId()));
        HashSet<String> newTags = new HashSet<>(flowInfo.getTags());
        HashSet<String> backup = new HashSet<>(newTags);
        newTags.removeAll(oldTags);
        oldTags.removeAll(backup);
        for (String tagId : newTags) {
            storeFlowTagMapper.insertStoreFlowTag(flowInfo.getFlowId(), tagId);
        }
        for (String tagId : oldTags) {
            storeFlowTagMapper.deleteStoreFlowTag(flowInfo.getFlowId(), tagId);
        }
        return new UpdateFlowResult(flowInfo.getFlowId());
    }

    @Override
    public GetFlowsByConditionResult getFlowsByCondition(QueryConditionInfo condition) {
        // 使用MyBatis Plus分页
        Page<StoreFlowInfo> page = new Page<>(condition.getPage(), condition.getLimit());

        // 根据条件查询流程信息，并进行分页
        IPage<StoreFlowInfo> pageInfo = storeFlowMapper.getFlowInfosByCondition(page, condition);
        List<StoreFlowInfo> res = pageInfo.getRecords();

        // 获取用户喜欢的流程ID列表
        Set<String> userLikes = new HashSet<>(likeMapper.getFlowIdsByUserId(condition.getUserId()));

        // 遍历查询结果，设置标签和用户喜欢状态
        for (StoreFlowInfo flow : res) {
            List<Tag> tagList = tagMapper.selectBatchIds(storeFlowTagMapper.getTagIdsByFlowId(flow.getFlowId()));
            flow.setTags(tagList);
            flow.setLikedByUser(userLikes.contains(flow.getFlowId()));
        }

        // 返回结果
        return new GetFlowsByConditionResult(true, pageInfo.getTotal(), res);
    }


    @Override
    public LikeFlowResult toggleLike(Like like) {
        Boolean liked = likeMapper.exist(like);
        if (liked) {
            likeMapper.delete(like);
        } else{
            likeMapper.insert(like);
        }
        Integer likeCount = likeMapper.getLikesCountByFlowId(like.getFlowId());
        return new LikeFlowResult(!liked, likeCount);
    }



    @Override
    public DownloadFlowResult downloadFlow(Download download) {
        if (!downloadMapper.exist(download)){
            downloadMapper.insert(download);
        }
        StoreFlow flow = storeFlowMapper.selectById(download.getFlowId());
        return DownloadFlowResult.from(flow);
    }

    @Override
    public GetTagsResult getTags() {
        List<Tag> tags = tagMapper.selectList(null);
        return new GetTagsResult(tags);
    }

    @Override
    public List<DownloadFlowResult> getAllFlows() {
        List<StoreFlow> flows =  storeFlowMapper.selectList(null);
        List<DownloadFlowResult> result = new ArrayList<>();
        for (StoreFlow flow : flows) {
            result.add(DownloadFlowResult.from(flow));
        }
        return result;
    }




}
